package com.zqj.project.common.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.*;
import com.zqj.project.common.enumeration.BaseEnum;

import java.util.*;
import java.util.function.Function;

/**
 * @Description: CollHelper
 * @Author: 22001010704 Zhang Qijian
 * @CreateTime: 2024/6/12 23:38
 * @Version: 1.0
 */
public final class CollHelper {

    private CollHelper() {
    }

    public static Map<String, String> getMap(BaseEnum[] list) {
        return uniqueIndex(Arrays.asList(list), BaseEnum::getCode, BaseEnum::getDesc);
    }

    public static <K, V, M> ImmutableMap<K, M> uniqueIndex(Iterable<V> values, Function<? super V, K> keyFunction, Function<? super V, M> valueFunction) {
        Iterator<V> iterator = values.iterator();
        Preconditions.checkNotNull(keyFunction);
        Preconditions.checkNotNull(valueFunction);
        ImmutableMap.Builder<K, M> builder = ImmutableMap.builder();

        while (iterator.hasNext()) {
            V value = iterator.next();
            builder.put(keyFunction.apply(value), valueFunction.apply(value));
        }

        try {
            return builder.build();
        } catch (IllegalArgumentException var6) {
            throw new IllegalArgumentException(var6.getMessage() + ".若要在键下索引多个值，请使用: Multimaps.index.", var6);
        }
    }

    public static <K, V, M> Multimap<K, M> iterableToMultiMap(Iterable<V> values, Function<? super V, K> keyFunction, Function<? super V, M> valueFunction) {
        Iterator<V> iterator = values.iterator();
        Preconditions.checkNotNull(keyFunction);
        Preconditions.checkNotNull(valueFunction);
        Multimap<K, M> builder = ArrayListMultimap.create();

        while (iterator.hasNext()) {
            V value = iterator.next();
            builder.put(keyFunction.apply(value), valueFunction.apply(value));
        }

        try {
            return builder;
        } catch (IllegalArgumentException var6) {
            throw new IllegalArgumentException(var6.getMessage() + ".若要在键下索引多个值，请使用: Multimaps.index.", var6);
        }
    }

    public static <K, V> Map<V, K> inverse(Map<K, V> map) {
        if (MapUtil.isEmpty(map)) {
            return Collections.emptyMap();
        } else {
            HashBiMap<K, V> biMap = HashBiMap.create();
            map.forEach(biMap::forcePut);
            return biMap.inverse();
        }
    }

    public static int initialCapacity(int size, float loadFactor) {
        return (int) (size / loadFactor + 1.0F);
    }

    public static int initialCapacity(int size) {
        return initialCapacity(size, 0.75F);
    }

    public static <T> List<String> split(Collection<T> list, Function<? super T, ?> function, CharSequence separator) {
        return CollUtil.isEmpty(list) ? Lists.newArrayList() : list.parallelStream().map(function).map(item -> CharSequenceUtil.splitToArray(String.valueOf(item), separator)).flatMap(Arrays::stream).filter(ObjectUtil::isNotEmpty).distinct().toList();
    }

    public static List<String> split(Collection<String> list, CharSequence separator) {
        return CollUtil.isEmpty(list) ? Lists.newArrayList() : list.parallelStream().map(item -> CharSequenceUtil.splitToArray(item, separator)).flatMap(Arrays::stream).filter(ObjectUtil::isNotEmpty).distinct().toList();
    }

    @SafeVarargs
    public static <E> List<E> asList(E... elements) {
        if (elements != null && elements.length != 0) {
            int capacity = computeListCapacity(elements.length);
            ArrayList<E> list = Lists.newArrayListWithCapacity(capacity);
            Collections.addAll(list, elements);
            return list;
        } else {
            return Collections.emptyList();
        }
    }

    @SafeVarargs
    public static <E> Set<E> asSet(E... elements) {
        if (elements != null && elements.length != 0) {
            LinkedHashSet<E> set = LinkedHashSet.newLinkedHashSet(elements.length * 4 / 3 + 1);
            Collections.addAll(set, elements);
            return set;
        } else {
            return Collections.emptySet();
        }
    }

    public static int computeListCapacity(int arraySize) {
        return (int) Math.min(5L + arraySize + (arraySize / 10), 2147483647L);
    }

}